<?php

namespace Biz\Middleware;

use Closure;
use Biz\Constants\ContainerConstants;
use Biz\Constants\ApplicationConstants;
use League\OAuth2\Server\ResourceServer;
use Lumen\Core\Exceptions\BusinessException;
use Laravel\Passport\Exceptions\MissingScopeException;
use League\OAuth2\Server\Exception\OAuthServerException;
use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory;

/**
 * AppAuthenticationToken.
 *
 * @license [http://www.85do.com] [杭州永奥网络科技有限公司]
 * @copyright Copyright (c) 2018-2026 Hangzhou Yongao Technology Co., Ltd. All rights reserved.
 */
class AppAuth
{
    /**
     * The Resource Server instance.
     *
     * @var \League\OAuth2\Server\ResourceServer
     */
    protected $server;

    /**
     * Create a new middleware instance.
     *
     * @param \League\OAuth2\Server\ResourceServer $server
     *
     * @return AppAuth
     */
    public function __construct(ResourceServer $server)
    {
        $this->server = $server;
    }

    /**
     * Handle an incoming request.
     *
     * @param \Illuminate\Http\Request $request
     * @param \Closure                 $next
     * @param mixed                    ...$scopes
     *
     * @throws BusinessException
     *
     * @return mixed
     */
    public function handle($request, Closure $next, ...$scopes)
    {
        if (false === $request->hasHeader(ApplicationConstants::HEADER_X_APP_AUTH_TOKEN)) {
            throw new BusinessException('抱歉，请传入应用认证Token');
        }

        $authToken = $request->header(ApplicationConstants::HEADER_X_APP_AUTH_TOKEN);
        if (empty($authToken)) {
            throw new BusinessException('抱歉，请传入应用认证Token');
        }

        $cloneRequest = clone $request;
        $bearerToken  = sprintf('Bearer %s', $authToken);
        $cloneRequest->server->set('HTTP_AUTHORIZATION', $bearerToken);
        $cloneRequest->headers->set('Authorization', $bearerToken);

        $psr = (new DiactorosFactory)->createRequest($cloneRequest);

        try {
            $psr = $this->server->validateAuthenticatedRequest($psr);
        } catch (OAuthServerException $e) {
            throw new BusinessException('抱歉，站点认证失败，请检查app_id及app_secret');
        }

        //dd($psr->getAttributes());

        app('app')->singleton(ContainerConstants::BIZ_CLIENT, function () use ($psr) {
            return $psr->getAttributes();
        });
        //dd($scopes);
        //dd($psr->getAttributes());
        //dd($cloneRequest->user());

        $this->validateScopes($psr, $scopes);

        $request->request->add($psr->getAttributes());

        return $next($request);
    }

    /**
     * Validate the scopes on the incoming request.
     *
     * @param \Psr\Http\Message\ServerRequestInterface $psr
     * @param array                                    $scopes
     *
     * @throws \Laravel\Passport\Exceptions\MissingScopeException
     *
     * @return void
     */
    protected function validateScopes($psr, $scopes)
    {
        if (in_array('*', $tokenScopes = $psr->getAttribute('oauth_scopes'))) {
            return;
        }

        foreach ($scopes as $scope) {
            if (! in_array($scope, $tokenScopes)) {
                throw new MissingScopeException($scope);
            }
        }
    }
}
